package spring_learn.a02;


import org.omg.CORBA.PUBLIC_MEMBER;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.Controller;
import org.xml.sax.InputSource;

/**
 * 常见的ApplicaitonContext的实现
 */
@SpringBootApplication
public class A02 {


    public static void main(String[] args) {
        //classPathApplicaitonContext();
        //FileSystemApplicaitonContext();
        //annotationApplicaitonContext();
        //webApplicationContext();

        DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
        String[] beanDefinitionNames = defaultListableBeanFactory.getBeanDefinitionNames();
        System.out.println("加载xml文件之前");
        for (String name:beanDefinitionNames)
            System.out.println(beanDefinitionNames);
        //加载xml文件并且解析bean
        //使用XmlBeanDefinitionReader和defaultListableBeanFactory实现了类似classPathApplicaitonContext的功能
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
        xmlBeanDefinitionReader.loadBeanDefinitions(new FileSystemResource("src/main/resources/a02.xml"));
        System.out.println("加载xml文件之后");
        for (String name:defaultListableBeanFactory.getBeanDefinitionNames())
            System.out.println(name);

    }

    /**
     * 四种常见的实现
     */

    //基于classpath的applicaitonContext
    public static void classPathApplicaitonContext(){
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("a02.xml");
        String[] beanDefinitionNames = classPathXmlApplicationContext.getBeanDefinitionNames();
        for (String name:beanDefinitionNames)
            System.out.println(name);
    }

    //基于磁盘路径的applicaitonContext
    public static void FileSystemApplicaitonContext(){
        FileSystemXmlApplicationContext fileSystemXmlApplicationContext =
                new FileSystemXmlApplicationContext("src/main/resources/a02.xml");
        String[] beanDefinitionNames = fileSystemXmlApplicationContext.getBeanDefinitionNames();
        for (String name:beanDefinitionNames)
            System.out.println(name);
    }

    //基于注解的applicaitonContext ！！
    public static void annotationApplicaitonContext(){
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
        annotationConfigApplicationContext.register(Config.class);
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (String name:beanDefinitionNames)
            System.out.println(name);
    }


    //web applicaiton context，用于web环境，内嵌服务器
    public static void webApplicationContext(){
        AnnotationConfigServletWebServerApplicationContext annotationConfigServletWebServerApplicationContext = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
        String[] beanDefinitionNames = annotationConfigServletWebServerApplicationContext.getBeanDefinitionNames();
        for (String name:beanDefinitionNames)
            System.out.println(name);
    }




    @Configuration
    static class WebConfig {
        @Bean
        public ServletWebServerFactory servletWebServerFactory(){
            return new TomcatServletWebServerFactory();
        }
        @Bean
        public DispatcherServlet dispatcherServlet() {
            return new DispatcherServlet();
        }
        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }
        @Bean("/hello")
        public Controller controller1() {
            return (request, response) -> {
                response.getWriter().print("hello");
                return null;
            };
        }
    }

    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2(Bean1 bean1) {
            Bean2 bean2 = new Bean2();
            bean2.setBean1(bean1);
            return bean2;
        }
    }

    static class Bean1 {
    }

    static class Bean2 {

        private Bean1 bean1;

        public void setBean1(Bean1 bean1) {
            this.bean1 = bean1;
        }

        public Bean1 getBean1() {
            return bean1;
        }
    }


}
